/******************************************************************************
 * * contact_move.c - implementation of contact move functions
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/
#include "contact_global.h"

/**
 * Set text for Contacts_Move_Quit interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Move_Quit_Set_Text(VOID *Ctrl)
{
    UI_Status_Desc_t *StatusDesc = (UI_Status_Desc_t *)Ctrl;
    lv_obj_t         *Label      = StatusDesc->ContLabel.Label;
    INT8             *Text1;
    INT8             *Text2;
    INT8             *Output;
    UINT8            Len;
    CONTACTS_MEMORY  Memory = g_ContactsMng.ContactOper.DestMemory;

    if (0 < g_ContactsMng.ContactOper.MarkNum)
    {
        if (1 == g_ContactsMng.ContactOper.MarkNum)
        {
            Text1 = (INT8 *)lv_lang_get_text(PHONE_TEXT_ID_CONTACT_NOT_MOVED);
        }
        else
        {
            Text1 = (INT8 *)lv_lang_get_text(PHONE_TEXT_ID_CONTACTS_NOT_MOVED);
        }

        if (g_ContactsMng.PhkStatus[Memory].Used == g_ContactsMng.PhkStatus[Memory].Total)
        {
            Text2  = (INT8 *)lv_lang_get_text(PHONE_TEXT_ID_TARGET_MEM_FULL);
            Len    = strlen(Text2) + 1 + 4 + strlen(Text1) + 1;
            Output = (INT8 *)Hal_Mem_Alloc(Len);
            sprintf(Output, "%s,%d%s", Text2,
                    g_ContactsMng.ContactOper.MarkNum + g_ContactsMng.ContactOper.NumberOfNoNumContact,
                    Text1);
        }
        else
        {
            Len    = 4 + strlen(Text1) + 1;
            Output = (INT8 *)Hal_Mem_Alloc(Len);
            sprintf(Output, "%d%s", g_ContactsMng.ContactOper.MarkNum, Text1);
        }

        lv_label_set_text(Label, Output);
        Hal_Mem_Free(Output);
    }
}

/**
 * Callback function for additional actions after Creating Contacts_Move_Quit interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Move_Quit_OnCreate(VOID *Ctrl)
{
    Contacts_Move_Quit_Set_Text(Ctrl);
    Contacts_Status_Interface_Timer_Start(Contacts_Timeout_Back_To_Prev_Interface);
}

/**
 * Callback function for restoring state on Contacts_Move_Quit interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Move_Quit_OnRestoreState(VOID *Ctrl)
{
    g_ContactsMng.InterfaceCtrl.Ctrl        = Ctrl;
    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_MOVE_QUIT;

    Contacts_Move_Quit_Set_Text(Ctrl);
} /* Contacts_Move_Quit_OnRestoreState */

/**
 * Callback function for destroying Contacts_Move_Quit interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Move_Quit_OnDestroy(VOID *Ctrl)
{
    Contacts_Interface_OnDestroy(Ctrl);
    g_ContactsMng.ContactOper.MarkNum = 0;
}

/**
 * Create Contacts_Move_Quit interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Move_Quit(VOID)
{
    UI_Status_Desc_t *StatusDesc;
    Nav_Func_List_t  FuncList;

    StatusDesc = (UI_Status_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Status_Desc_t));
    Hal_Mem_Set(StatusDesc, 0, sizeof(UI_Status_Desc_t));

    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_MOVE_QUIT;
    g_ContactsMng.InterfaceCtrl.Ctrl        = (VOID *)StatusDesc;

    StatusDesc->ContLabel.TxtId      = PHONE_TEXT_ID_MOVED;
    StatusDesc->ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    StatusDesc->ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    StatusDesc->ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    StatusDesc->ContImg.Img  = SYMBOL_CHECKED;
    StatusDesc->ContImgAlign = LV_ALIGN_IN_TOP_RIGHT;

    StatusDesc->KeyFunc = Contacts_Status_Interface_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Status_Create;
    FuncList.OnCreate       = Contacts_Move_Quit_OnCreate;
    FuncList.OnRestoreState = Contacts_Move_Quit_OnRestoreState;
    FuncList.OnDestroy      = Contacts_Move_Quit_OnDestroy;

    Nav_Backward_And_Forward(ACT_ID_ANY, ACT_ID_CONTACTS, ACT_ID_CONTACTS_MOVE_QUIT, &FuncList, g_ContactsMng.InterfaceCtrl.Ctrl);
}


/**
 * Set text for Contacts_Moved interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Moved_Set_Text(VOID *Ctrl)
{
    UI_Status_Desc_t *StatusDesc = (UI_Status_Desc_t *)Ctrl;
    lv_obj_t         *Label      = StatusDesc->ContLabel.Label;
    const INT8       *Text1;
    const INT8       *Text2;
    const INT8       *Text3;
    INT8             *Output;
    UINT8            Len;

    if ((TRUE == g_ContactsMng.ContactOper.NameModifedFlg)
        || (0 < g_ContactsMng.ContactOper.NumberOfNoNumContact))
    {
        Text1 = lv_lang_get_text(PHONE_TEXT_ID_MOVED);
        Len = strlen(Text1) + 1;
        if (TRUE == g_ContactsMng.ContactOper.NameModifedFlg)
        {
            Text2 = lv_lang_get_text(PHONE_TEXT_ID_NAME_MODIFIED);
            Len += strlen(Text2);
        }
        if (0 < g_ContactsMng.ContactOper.NumberOfNoNumContact)
        {
            Text3 = lv_lang_get_text(PHONE_TEXT_ID_NO_NUMBER_NO_MOVE);
            Len += strlen(Text3) + 2;
        }
        Output = (INT8 *)Hal_Mem_Alloc(Len);
        Hal_Mem_Copy(Output, Text1, strlen(Text1) + 1);
        if (TRUE == g_ContactsMng.ContactOper.NameModifedFlg)
        {
            strcat(Output, Text2);
        }
        if (0 < g_ContactsMng.ContactOper.NumberOfNoNumContact)
        {
            strcat(Output, "\n");
            strcat(Output, Text3);
        }
        lv_label_set_text(Label, Output);
        Hal_Mem_Free(Output);
    }
}

/**
 * Callback function for additional actions after Creating Contacts_Moved interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Moved_OnCreate(VOID *Ctrl)
{
    Contacts_Moved_Set_Text(Ctrl);
    Contacts_Status_Interface_Timer_Start(Contacts_Timeout_Back_To_Prev_Interface);
}

/**
 * Callback function for restoring state on Contacts_Moved interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Moved_OnRestoreState(VOID *Ctrl)
{
    g_ContactsMng.InterfaceCtrl.Ctrl        = Ctrl;
    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_MOVED;

    Contacts_Moved_Set_Text(Ctrl);
}

/**
 * Callback function for destroying Contacts_Moved interface which will be popped from stack
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Moved_OnDestroy(VOID *Ctrl)
{
    Contacts_Timer_Stop();
    Hal_Mem_Free(Ctrl);
    g_ContactsMng.ContactOper.NameModifedFlg = FALSE;
}

/**
 * Create Contacts_Moved interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Moved(VOID)
{
    UI_Status_Desc_t *StatusDesc;
    Nav_Func_List_t  FuncList;

    StatusDesc = (UI_Status_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Status_Desc_t));
    Hal_Mem_Set(StatusDesc, 0, sizeof(UI_Status_Desc_t));

    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_MOVED;
    g_ContactsMng.InterfaceCtrl.Ctrl        = (VOID *)StatusDesc;

    StatusDesc->ContLabel.TxtId      = PHONE_TEXT_ID_MOVED;
    StatusDesc->ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    StatusDesc->ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    StatusDesc->ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    StatusDesc->ContImg.Img  = SYMBOL_CHECKED;
    StatusDesc->ContImgAlign = LV_ALIGN_IN_TOP_RIGHT;

    StatusDesc->KeyFunc = Contacts_Status_Interface_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Status_Create;
    FuncList.OnCreate       = Contacts_Moved_OnCreate;
    FuncList.OnRestoreState = Contacts_Moved_OnRestoreState;
    FuncList.OnDestroy      = Contacts_Moved_OnDestroy;

    Nav_Backward_And_Forward(ACT_ID_ANY, ACT_ID_CONTACTS, ACT_ID_CONTACTS_MOVED, &FuncList, g_ContactsMng.InterfaceCtrl.Ctrl);
}

/**
 * Callback function for handling key pressed on Contacts_Moving interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Contacts_Moving_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT: // quit
            if (0 < g_ContactsMng.ContactOper.MarkNum)
            {
                g_ContactsMng.ContactOper.ProcQuit = TRUE;
                Contacts_Create_Contacts_Move_Quit();
            }
            break;

        case KEY_END:
            g_ContactsMng.ContactOper.ProcQuit = TRUE;
            Nav_Home(ACT_ID_ANY);
            break;

        default:
            break;
        } /* switch */
    }

    return(1);
}

/**
 * Callback function for restoring state on Contacts_Moving interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Moving_OnRestoreState(VOID *Ctrl)
{
    g_ContactsMng.InterfaceCtrl.Ctrl        = Ctrl;
    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_MOVING;
}

/**
 * Create Contacts_Moving interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Moving(VOID)
{
    UI_Normal_NoTitle_Desc_t *Interface;
    Nav_Func_List_t          FuncList;

    Interface = (UI_Normal_NoTitle_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_NoTitle_Desc_t));
    Hal_Mem_Set(Interface, 0, sizeof(UI_Normal_NoTitle_Desc_t));

    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_MOVING;
    g_ContactsMng.InterfaceCtrl.Ctrl        = (VOID *)Interface;

    Interface->ContenCont.ContLabel.TxtId      = PHONE_TEXT_ID_MOVING;
    Interface->ContenCont.ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    Interface->ContenCont.ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    Interface->ContenCont.ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    Interface->ContenCont.ContImgAlign     = LV_ALIGN_IN_BOTTOM_LEFT;
    Interface->ContenCont.ContImg.ImgAlign = LV_ALIGN_IN_BOTTOM_LEFT;
    Interface->ContenCont.ContImg.Img      = IMG_PROGRESS_BAR;

    Interface->ButtonBar.ButtonL.Valid = FALSE;
    Interface->ButtonBar.ButtonM.Valid = FALSE;
    Interface->ButtonBar.ButtonR.Valid = TRUE;
    Interface->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_QUIT;

    Interface->KeyFunc = Contacts_Moving_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Normal_NoTitle_Create;
    FuncList.OnRestoreState = Contacts_Moving_OnRestoreState;
    FuncList.OnSaveState    = Contacts_Interface_OnSaveState;
    FuncList.OnDestroy      = Contacts_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CONTACTS_MOVING, &FuncList, g_ContactsMng.InterfaceCtrl.Ctrl);
}

/**
 * Moving
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Process_Move_End_Handle(VOID)
{
    printf("%s: MarkNum %d, ProcQuit %d\n",
           __FUNCTION__, g_ContactsMng.ContactOper.MarkNum, g_ContactsMng.ContactOper.ProcQuit);

    g_ContactsMng.ContactOper.Action = CONTACTS_ACTION_NULL;
    _lv_ll_clear(&g_ContactsMng.ContactOper.SrcMemList);

    if (NULL == Nav_Get_Param(ACT_ID_CONTACTS))
    {
        printf("%s: not in contacts\n", __FUNCTION__);
        g_ContactsMng.ContactOper.MarkNum = 0;
        g_ContactsMng.ContactOper.ProcQuit = FALSE;
        return;
    }

    Contacts_Reset_Contacts_Interface();

    if (Nav_Get_Top() != g_ContactsMng.InterfaceCtrl.InterfaceId)
    {   /* Contacts_Moving interface was covered by other interface */
        Nav_Forward(ACT_ID_CONTACTS_MOVING, ACT_ID_CONTACTS, NULL, NULL);
    }
    else if (0 == g_ContactsMng.ContactOper.MarkNum)
    {
        Contacts_Create_Contacts_Moved();
    }
    else if (g_ContactsMng.ContactOper.ProcQuit)
    {
        /*return to desktop or move quit interface has been created*/
        g_ContactsMng.ContactOper.ProcQuit = FALSE;
    }
    else
    {
        Contacts_Create_Contacts_Move_Quit();
    }
}

/**
 * Process for moving multiple contacts, first copy then delete
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Process_Move_Multiple_Contacts(VOID)
{
    Contacts_List_t   *Contact;
    Contacts_List_t   *Node;
    Contacts_Info_t   *ContactInfo;
    lv_ll_t           *ContactsList;
    UINT16            Index;
    UINT8             Bit;
    CONTACTS_MEMORY   Memory;
    UINT8             NvBitmap;

    ContactsList = Contacts_Get_Contacts_Operation_List(NULL);

    if (NULL == g_ContactsMng.InterfaceCtrl.Focus)
    {
        g_ContactsMng.InterfaceCtrl.Focus = _lv_ll_get_head(ContactsList);
    }

    while (NULL != g_ContactsMng.InterfaceCtrl.Focus)
    {
        Contact = g_ContactsMng.InterfaceCtrl.Focus;
        g_ContactsMng.InterfaceCtrl.Focus = _lv_ll_get_next(ContactsList, Contact);

        if (FALSE == Contact->ContactInfo->MarkFlg)
        {
            continue;
        }

        g_ContactsMng.ContactOper.MarkNum--;

        if (0 == strlen(Contact->ContactInfo->Number))
        {
            g_ContactsMng.ContactOper.NumberOfNoNumContact++;
            printf("%s: not move contact %s without number, MarkNum %d, NoNum %d\n",
                   __FUNCTION__, Contact->ContactInfo->Name, g_ContactsMng.ContactOper.MarkNum,
                   g_ContactsMng.ContactOper.NumberOfNoNumContact);
            Contact->ContactInfo->MarkFlg = FALSE;
            if (0 == g_ContactsMng.ContactOper.MarkNum)
            {
                Contacts_Process_Move_End_Handle();
                return;
            }

            continue;
        }

        // copy contact to target memory
        ContactInfo = (Contacts_Info_t *)Hal_Mem_Alloc(sizeof(Contacts_Info_t));
        Hal_Mem_Copy(ContactInfo->Name, Contact->ContactInfo->Name, CONTACTS_MAX_NAME_LENGTH);
        if (CONTACTS_MEMORY_PHONE != g_ContactsMng.ContactOper.DestMemory)
        {
            /*move to sim, adjust the lenght of name*/
            Contacts_Adjust_Name_Len_For_Sim(ContactInfo->Name);
        }
        Hal_Mem_Copy(ContactInfo->Number, Contact->ContactInfo->Number, CONTACTS_MAX_NUMBER_LENGTH);
        ContactInfo->MarkFlg        = FALSE;
        ContactInfo->ToneIndex      = IF_CONTACTS_DEFAULT_TONE;
        ContactInfo->MemoryAndIndex = Contacts_Set_Contact_Memory(g_ContactsMng.ContactOper.DestMemory);

        Contacts_Add_Contact_With_Name_Modified(ContactInfo, NULL);

        // record the new contact, add writtenindex if write to sim successfully
        g_ContactsMng.InterfaceCtrl.ContactDetail = ContactInfo;

        if (CONTACTS_MEMORY_PHONE == g_ContactsMng.ContactOper.DestMemory)
        {
            Contacts_Add_Contact_To_Nvm(ContactInfo);
        }
        else
        {
            Contacts_Send_Write_Phonebook_Req(g_ContactsMng.ContactOper.DestMemory,
                                              ContactInfo->Name, ContactInfo->Number,
                                              MMI_MODEM_CONTACT_INDEX_INVALID);
        }

        // delete contact from source memory
        Index = Contacts_Get_Contact_Index(Contact->ContactInfo->MemoryAndIndex);

        /* Contacts_Speed_Dials_Update_Contact(Contact->ContactInfo, NULL, NULL); */

        if (CONTACTS_MEMSEL_ALL != g_ContactsMng.ContactsMemSel.MemSel)
        {
            if (Contacts_Is_In_MemSel(Contact->ContactInfo->MemoryAndIndex, g_ContactsMng.ContactsMemSel.MemSel))
            {
                /* delete contact from ListForSpecMem */
                g_ContactsMng.ContactsMemSel.ContactsCount--;
                Node = _lv_ll_get_head(&g_ContactsMng.ContactsMemSel.ListForSpecMem);
                while (NULL != Node)
                {
                    if (Contact->ContactInfo == Node->ContactInfo)
                    {
                        _lv_ll_remove(&g_ContactsMng.ContactsMemSel.ListForSpecMem, Node);
                        Hal_Mem_Free(Node);
                        break;
                    }

                    Node = _lv_ll_get_next(&g_ContactsMng.ContactsMemSel.ListForSpecMem, Node);
                }
            }
        }

        /* delete contact from the node(g_ContactsMng.InterfaceCtrl.FocusContact) of ContactsList,
         * avoid the search from the beginning of ContactsList every time */
        if (NULL == g_ContactsMng.InterfaceCtrl.FocusContact)
        {
            g_ContactsMng.InterfaceCtrl.FocusContact = _lv_ll_get_head(&g_ContactsMng.ContactsList);
        }
        while (NULL != g_ContactsMng.InterfaceCtrl.FocusContact)
        {
            Node = g_ContactsMng.InterfaceCtrl.FocusContact;
            g_ContactsMng.InterfaceCtrl.FocusContact = _lv_ll_get_next(&g_ContactsMng.ContactsList, Node);
            if (Contact->ContactInfo == Node->ContactInfo)
            {
                _lv_ll_remove(&g_ContactsMng.ContactsList, Node);
                Hal_Mem_Free(Node->ContactInfo);
                Hal_Mem_Free(Node);
                g_ContactsMng.ContactsCount--;
                break;
            }
        }

        Memory = g_ContactsMng.ContactOper.SrcMemory;
        g_ContactsMng.PhkStatus[Memory].Used--;
        if (CONTACTS_MEMORY_PHONE == Memory)
        {
            /* delete the marked contact from NVM */
            Bit   = Index % 8;
            Index = Index / 8;
            if (1 != UI_NV_Read_Req(NV_SECTION_UI_CONTACTS_BITMAP, Index, 1, &NvBitmap))
            {
                /* error */
                return;
            }

            NvBitmap &= ~(0x01 << Bit);
            if (1 != UI_NV_Write_Req(NV_SECTION_UI_CONTACTS_BITMAP, Index, 1, &NvBitmap))
            {
                /* error */
                return;
            }
        }
        else
        {
            Contacts_Send_Write_Phonebook_Req(Memory, NULL, NULL, Index);
        }

        break;
    }
} /* Contacts_Process_Move_Multiple_Contacts */

/**
 * Security code check confirm for contacts move operation
 * param (in) Result: SETTING_RESULT
 * return  VOID
 */
VOID Contacts_Move_Check_Security_Cnf(SETTING_RESULT Result)
{
    if (SETTING_OK != Result)
    {
        return;
    }

    printf("%s: from %d to %d, markflg %d, marknum %d\n",
           __FUNCTION__,
           g_ContactsMng.ContactOper.SrcMemory,
           g_ContactsMng.ContactOper.DestMemory,
           g_ContactsMng.InterfaceCtrl.SelAllFlg,
           g_ContactsMng.ContactOper.MarkNum);

    g_ContactsMng.ContactOper.Action = CONTACTS_ACTION_MOVING;

    Contacts_Create_Contacts_Moving();

    g_ContactsMng.InterfaceCtrl.Focus              = NULL; // direct to SrcMemList
    g_ContactsMng.InterfaceCtrl.FocusContact       = NULL; // direct to ContactsList
    g_ContactsMng.InterfaceCtrl.ContactDetail      = NULL;
    g_ContactsMng.ContactOper.NameModifedFlg       = FALSE;
    g_ContactsMng.ContactOper.NumberOfNoNumContact = 0;
    Contacts_Process_Move_Multiple_Contacts();
}

/**
 * Callback function for handling key pressed on Contacts_Move_Ready interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Contacts_Move_Ready_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            break;

        case KEY_OK:
            Setting_Check_Security_Req(Contacts_Move_Check_Security_Cnf);
            break;

        default:
            break;
        } /* switch */
    }

    return(1);
}

/**
 * Callback function for additional actions after Creating Contacts_Move_Ready interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Move_Ready_OnCreate(VOID *Ctrl)
{
    UI_Normal_NoTitle_Desc_t *Interface = (UI_Normal_NoTitle_Desc_t *)Ctrl;
    lv_obj_t                 *Label     = Interface->ContenCont.ContLabel.Label;
    INT8                     *Text1;
    INT8                     *Text2;
    UINT8                    Len;
    INT8                     *Output;

    Text1 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_MOVE));
    if (1 < g_ContactsMng.ContactOper.MarkNum)
    {
        Text2 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_CONTACTS_Q));
    }
    else
    {
        Text2 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_CONTACT_Q));
    }

    Len    = strlen(Text1) + 5 + strlen(Text2) + 1;
    Output = (INT8 *)Hal_Mem_Alloc(Len);
    sprintf(Output, "%s %d%s", Text1, g_ContactsMng.ContactOper.MarkNum, Text2);
    lv_label_set_text(Label, Output);
    Hal_Mem_Free(Output);
}

/**
 * Callback function for restoring state on Contacts_Move_Ready interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Move_Ready_OnRestoreState(VOID *Ctrl)
{
    UI_Normal_NoTitle_Desc_t *Interface = (UI_Normal_NoTitle_Desc_t *)Ctrl;
    lv_obj_t                 *Label     = Interface->ContenCont.ContLabel.Label;
    INT8                     *Text1;
    INT8                     *Text2;
    UINT8                    Len;
    INT8                     *Output;

    g_ContactsMng.InterfaceCtrl.Ctrl        = Ctrl;
    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_MOVE_READY;

    Text1 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_MOVE));
    if (1 < g_ContactsMng.ContactOper.MarkNum)
    {
        Text2 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_CONTACTS_Q));
    }
    else
    {
        Text2 = (INT8 *)(lv_lang_get_text(PHONE_TEXT_ID_CONTACT_Q));
    }

    Len    = strlen(Text1) + 5 + strlen(Text2) + 1;
    Output = (INT8 *)Hal_Mem_Alloc(Len);
    sprintf(Output, "%s %d%s", Text1, g_ContactsMng.ContactOper.MarkNum, Text2);
    lv_label_set_text(Label, Output);
    Hal_Mem_Free(Output);
}

/**
 * Create Contacts_Move_Ready interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Move_Ready(VOID)
{
    UI_Normal_NoTitle_Desc_t *Interface;
    Nav_Func_List_t          FuncList;

    Interface = (UI_Normal_NoTitle_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_NoTitle_Desc_t));
    Hal_Mem_Set(Interface, 0, sizeof(UI_Normal_NoTitle_Desc_t));

    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_MOVE_READY;
    g_ContactsMng.InterfaceCtrl.Ctrl        = (VOID *)Interface;

    Interface->ContenCont.ContLabel.TxtId      = LV_LANG_TXT_ID_NONE;
    Interface->ContenCont.ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    Interface->ContenCont.ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;
    Interface->ContenCont.ContLabelAlign       = LV_ALIGN_IN_TOP_LEFT;

    Interface->ButtonBar.ButtonL.Valid = FALSE;

    Interface->ButtonBar.ButtonM.Valid = TRUE;
    Interface->ButtonBar.ButtonM.TxtId = PHONE_TEXT_ID_OK;

    Interface->ButtonBar.ButtonR.Valid = TRUE;
    Interface->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;

    Interface->KeyFunc = Contacts_Move_Ready_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Normal_NoTitle_Create;
    FuncList.OnCreate       = Contacts_Move_Ready_OnCreate;
    FuncList.OnRestoreState = Contacts_Move_Ready_OnRestoreState;
    FuncList.OnDestroy      = Contacts_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CONTACTS_MOVE_READY, &FuncList, g_ContactsMng.InterfaceCtrl.Ctrl);
}

/**
 * Callback function for handling key pressed on Contacts_Move interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Contacts_Move_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UINT8 Ret = 1;

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_UP:
        case KEY_LEFT:
        case KEY_DOWN:
        case KEY_RIGHT:
            Ret = Contacts_Com_Select_Multi_Press_Direction_Key(Key_Val);
            break;

        case KEY_OK:
            Ret = 0; // call the default key function
            break;

        case KEY_SOFTLEFT: // copy marked contacts to target memory
            if (0 != g_ContactsMng.ContactOper.MarkNum)
            {
                Contacts_Create_Contacts_Move_Ready();
            }
            break;

        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
}

/**
 * Create Contacts_Move interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Move(VOID)
{
    g_ContactsMng.ContactOper.Action = CONTACTS_ACTION_MOVE;
    Contacts_Make_Src_Mem_List();
    Contacts_Com_Create_Select_Multi_Contacts(ACT_ID_CONTACTS_MOVE, Contacts_Move_Key_Cb);
}

/**
 * Action if pressing from phone to SIM1 button on Contacts_Move_Select interface
 * param (in) lv_obj_t *Btn,lv_event_t event
 * return  void
 */
void Contacts_Move_Select_Btn_From_Phone_To_Sim1_Cb(lv_obj_t *Btn,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    if (g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM1].Total ==
        g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM1].Used)
    {
        Contacts_Create_Contacts_Full();
    }
    else if (0 == g_ContactsMng.PhkStatus[CONTACTS_MEMORY_PHONE].Used)
    {
        Contacts_Create_Contacts_Empty();
    }
    else
    {
        g_ContactsMng.ContactOper.SrcMemory  = CONTACTS_MEMORY_PHONE;
        g_ContactsMng.ContactOper.DestMemory = CONTACTS_MEMORY_SIM1;
        Contacts_Create_Contacts_Move();
    }
}

/**
 * Action if pressing from SIM1 to phone button on Contacts_Move_Select interface
 * param (in) lv_obj_t *Btn,lv_event_t event
 * return  void
 */
void Contacts_Move_Select_Btn_From_Sim1_To_Phone_Cb(lv_obj_t *Btn,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    if (g_ContactsMng.PhkStatus[CONTACTS_MEMORY_PHONE].Total ==
        g_ContactsMng.PhkStatus[CONTACTS_MEMORY_PHONE].Used)
    {
        Contacts_Create_Contacts_Full();
    }
    else if (0 == g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM1].Used)
    {
        Contacts_Create_Contacts_Empty();
    }
    else
    {
        g_ContactsMng.ContactOper.SrcMemory  = CONTACTS_MEMORY_SIM1;
        g_ContactsMng.ContactOper.DestMemory = CONTACTS_MEMORY_PHONE;
        Contacts_Create_Contacts_Move();
    }
}

/**
 * Action if pressing from phone to SIM2 button on Contacts_Move_Select interface
 * param (in) lv_obj_t *Btn,lv_event_t event
 * return  void
 */
void Contacts_Move_Select_Btn_From_Phone_To_Sim2_Cb(lv_obj_t *Btn,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    if (g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM2].Total ==
        g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM2].Used)
    {
        Contacts_Create_Contacts_Full();
    }
    else if (0 == g_ContactsMng.PhkStatus[CONTACTS_MEMORY_PHONE].Used)
    {
        Contacts_Create_Contacts_Empty();
    }
    else
    {
        g_ContactsMng.ContactOper.SrcMemory  = CONTACTS_MEMORY_PHONE;
        g_ContactsMng.ContactOper.DestMemory = CONTACTS_MEMORY_SIM2;
        Contacts_Create_Contacts_Move();
    }
}

/**
 * Action if pressing from SIM2 to phone button on Contacts_Copy_Select interface
 * param (in) lv_obj_t *Btn,lv_event_t event
 * return  void
 */
void Contacts_Move_Select_Btn_From_Sim2_To_Phone_Cb(lv_obj_t *Btn,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    if (g_ContactsMng.PhkStatus[CONTACTS_MEMORY_PHONE].Total ==
        g_ContactsMng.PhkStatus[CONTACTS_MEMORY_PHONE].Used)
    {
        Contacts_Create_Contacts_Full();
    }
    else if (0 == g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM2].Used)
    {
        Contacts_Create_Contacts_Empty();
    }
    else
    {
        g_ContactsMng.ContactOper.SrcMemory  = CONTACTS_MEMORY_SIM2;
        g_ContactsMng.ContactOper.DestMemory = CONTACTS_MEMORY_PHONE;
        Contacts_Create_Contacts_Move();
    }
}

/**
 * Action if pressing from SIM1 to SIM2 button on Contacts_Move_Select interface
 * param (in) lv_obj_t *Btn,lv_event_t event
 * return  void
 */
void Contacts_Move_Select_Btn_From_Sim1_To_Sim2_Cb(lv_obj_t *Btn,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    if (g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM2].Total ==
        g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM2].Used)
    {
        Contacts_Create_Contacts_Full();
    }
    else if (0 == g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM1].Used)
    {
        Contacts_Create_Contacts_Empty();
    }
    else
    {
        g_ContactsMng.ContactOper.SrcMemory  = CONTACTS_MEMORY_SIM1;
        g_ContactsMng.ContactOper.DestMemory = CONTACTS_MEMORY_SIM2;
        Contacts_Create_Contacts_Move();
    }
}

/**
 * Action if pressing from SIM2 to SIM1 button on Contacts_Move_Select interface
 * param (in) lv_obj_t *Btn,lv_event_t event
 * return  void
 */
void Contacts_Move_Select_Btn_From_Sim2_To_Sim1_Cb(lv_obj_t *Btn,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    if (g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM1].Total ==
        g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM1].Used)
    {
        Contacts_Create_Contacts_Full();
    }
    else if (0 == g_ContactsMng.PhkStatus[CONTACTS_MEMORY_SIM2].Used)
    {
        Contacts_Create_Contacts_Empty();
    }
    else
    {
        g_ContactsMng.ContactOper.SrcMemory  = CONTACTS_MEMORY_SIM2;
        g_ContactsMng.ContactOper.DestMemory = CONTACTS_MEMORY_SIM1;
        Contacts_Create_Contacts_Move();
    }
}

/**
 * Callback function for restoring state on Contacts_Move_Select interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Move_Select_OnRestoreState(VOID *Ctrl)
{
    g_ContactsMng.InterfaceCtrl.Ctrl        = Ctrl;
    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_MOVE_SELECT;
}

/**
 * Create Contacts_Move_Select interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Move_Select(VOID)
{
    UI_Normal_List_Only_Desc_t *NormalLstOnlyDesc;
    Nav_Func_List_t            FuncList;
    UINT8                      i = 0;
    UINT32                     Len;

    NormalLstOnlyDesc =
        (UI_Normal_List_Only_Desc_t *)Hal_Mem_Alloc(sizeof(UI_Normal_List_Only_Desc_t));
    Hal_Mem_Set(NormalLstOnlyDesc, 0, sizeof(UI_Normal_List_Only_Desc_t));

    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_MOVE_SELECT;
    g_ContactsMng.InterfaceCtrl.Ctrl        = (VOID *)NormalLstOnlyDesc;

    NormalLstOnlyDesc->TitleBar.TxtId      = PHONE_TEXT_ID_MOVE;
    NormalLstOnlyDesc->TitleBar.TxtAlign   = LV_LABEL_ALIGN_CENTER;
    NormalLstOnlyDesc->TitleBar.LabelAlign = LV_ALIGN_IN_TOP_LEFT;

    if (  (CONTACTS_PHONEBOOK_STATUS_READ_DONE == g_ContactsMng.PhonebookStatus[0])
       && (CONTACTS_PHONEBOOK_STATUS_READ_DONE == g_ContactsMng.PhonebookStatus[1]))
    {
        NormalLstOnlyDesc->List.ListButtonCnt = 6;
    }
    else if (CONTACTS_PHONEBOOK_STATUS_READ_DONE == g_ContactsMng.PhonebookStatus[0])
    {
        NormalLstOnlyDesc->List.ListButtonCnt = 2;
    }
    else if (CONTACTS_PHONEBOOK_STATUS_READ_DONE == g_ContactsMng.PhonebookStatus[1])
    {
        NormalLstOnlyDesc->List.ListButtonCnt = 2;
    }
    else
    {
        /* error */
        return;
    }
    Len = sizeof(UI_Button_Desc_t) *
          NormalLstOnlyDesc->List.ListButtonCnt;
    NormalLstOnlyDesc->List.ButtonList = (UI_Button_Desc_t *)Hal_Mem_Alloc(Len);
    Hal_Mem_Set(NormalLstOnlyDesc->List.ButtonList, 0, Len);

    if (CONTACTS_PHONEBOOK_STATUS_READ_DONE == g_ContactsMng.PhonebookStatus[0])
    {   /* SIM1 prsent */
        NormalLstOnlyDesc->List.ButtonList[i].Valid        = TRUE;
        NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex  = i;
        NormalLstOnlyDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_FPTS1;
        NormalLstOnlyDesc->List.ButtonList[i++].ReleaseFun =
            Contacts_Move_Select_Btn_From_Phone_To_Sim1_Cb;

        NormalLstOnlyDesc->List.ButtonList[i].Valid        = TRUE;
        NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex  = i;
        NormalLstOnlyDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_FS1TP;
        NormalLstOnlyDesc->List.ButtonList[i++].ReleaseFun =
            Contacts_Move_Select_Btn_From_Sim1_To_Phone_Cb;
    }

    if (CONTACTS_PHONEBOOK_STATUS_READ_DONE == g_ContactsMng.PhonebookStatus[1])
    {   /* SIM2 prsent */
        NormalLstOnlyDesc->List.ButtonList[i].Valid        = TRUE;
        NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex  = i;
        NormalLstOnlyDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_FPTS2;
        NormalLstOnlyDesc->List.ButtonList[i++].ReleaseFun =
            Contacts_Move_Select_Btn_From_Phone_To_Sim2_Cb;

        NormalLstOnlyDesc->List.ButtonList[i].Valid        = TRUE;
        NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex  = i;
        NormalLstOnlyDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_FS2TP;
        NormalLstOnlyDesc->List.ButtonList[i++].ReleaseFun =
            Contacts_Move_Select_Btn_From_Sim2_To_Phone_Cb;

        if (CONTACTS_PHONEBOOK_STATUS_READ_DONE == g_ContactsMng.PhonebookStatus[0])
        {   /* SIM1 prsent */
            NormalLstOnlyDesc->List.ButtonList[i].Valid        = TRUE;
            NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex  = i;
            NormalLstOnlyDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_FS1TS2;
            NormalLstOnlyDesc->List.ButtonList[i++].ReleaseFun =
                Contacts_Move_Select_Btn_From_Sim1_To_Sim2_Cb;

            NormalLstOnlyDesc->List.ButtonList[i].Valid        = TRUE;
            NormalLstOnlyDesc->List.ButtonList[i].ButtonIndex  = i;
            NormalLstOnlyDesc->List.ButtonList[i].TxtId        = PHONE_TEXT_ID_FS2TS1;
            NormalLstOnlyDesc->List.ButtonList[i++].ReleaseFun =
                Contacts_Move_Select_Btn_From_Sim2_To_Sim1_Cb;
        }
    }

    NormalLstOnlyDesc->BtnBar.ButtonL.Valid = FALSE;
    NormalLstOnlyDesc->BtnBar.ButtonM.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonM.TxtId = PHONE_TEXT_ID_SELECT;
    NormalLstOnlyDesc->BtnBar.ButtonR.Valid = TRUE;
    NormalLstOnlyDesc->BtnBar.ButtonR.TxtId = PHONE_TEXT_ID_BACK;

    NormalLstOnlyDesc->KeyFunc = Contacts_Normal_List_Interface_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Normal_List_Only_Create;
    FuncList.OnSaveState    = Contacts_Interface_OnSaveState;
    FuncList.OnRestoreState = Contacts_Move_Select_OnRestoreState;
    FuncList.OnDestroy      = Contacts_Normal_List_Interface_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CONTACTS_MOVE_SELECT, &FuncList, g_ContactsMng.InterfaceCtrl.Ctrl);
} /* Contacts_Create_Contacts_Copy_Select */
